//
//						Events.h
//

#ifndef __NEWA_EVENTS_H
#define __NEWA_EVENTS_H

#pragma message( "INCLUDING FILE: " __FILE__ )

#include <loki/Functor.h>
#include <vector>
#include <map>
#include "FctorUtils.h"

namespace newa
{
	enum e_eventid 
	{ 
		EVCLICK, 
		EVPAINT, 
		EVLMSDOWN, 
		EVLMSUP, 
		EVRMSDOWN, 
		EVRMSUP,
		EVMSMOVE, 
		EVMSENTER, 
		EVMSLEAVE, 
		EVKEYDOWN, 
		EVKEYUP, 
		EVCHAR,
		EVRESIZE, 
		EVMOVE 
	};

	template< e_eventid ID >
	class EventTraits;

	class EventBase
	{
	};

	template < e_eventid ID  >
	class Event : public EventBase
	{
    public:
		typedef typename EventTraits< ID >::HandlerArgs ArgsType;
		typedef typename EventTraits< ID >::HandlerFtor Handler;

		bool operator() ( const ArgsType & args )
		{
			if( m_handler ) {
				xloki::Invoke ( m_handler, args );
				return true;
			}

			return false;
		}

		void operator = ( const Handler& handler )
		{
			m_handler = handler;
		}

	private:
		Handler m_handler;
	};

	/************************************************************************/
	/* EventTraits                                                          */
	/************************************************************************/

	template< e_eventid ID >
	class DispatchSelfOnly;
	template< e_eventid ID >
	class DispatchMouseEvent;
/*
	template< e_eventid ID >
	class DispatchClickEvent;
*/
	template< e_eventid ID >
	class DispatchPaint;
	template< e_eventid ID >
	class DispatchFocused;

	template<>
	class EventTraits< EVCLICK >
	{
	public:
		static const e_eventid ID = EVCLICK;
		typedef NoArgs									DsptArgsList;
		typedef Loki::Tuple< DsptArgsList >				DsptArgs;
		typedef DispatchMouseEvent< ID >				DispatcherType;
		typedef DsptArgsList							HandlerArgsList;
		typedef Loki::Tuple< HandlerArgsList >			HandlerArgs;
		typedef Loki::Functor< void, HandlerArgsList >	HandlerFtor;
	};

	template<>
	class EventTraits< EVPAINT >
	{
	public:
		static const e_eventid ID = EVPAINT;
		typedef NoArgs									DsptArgsList;
		typedef Loki::Tuple< DsptArgsList >				DsptArgs;
		typedef DispatchPaint< ID >						DispatcherType;
		typedef PaintEventArgs							HandlerArgsList;
		typedef Loki::Tuple< HandlerArgsList >			HandlerArgs;
		typedef Loki::Functor< void, HandlerArgsList >	HandlerFtor;
	};

	template<>
	class EventTraits< EVLMSDOWN >
	{
	public:
		static const e_eventid ID = EVLMSDOWN;
		typedef MouseEventArgs					DsptArgsList;
		typedef Loki::Tuple< DsptArgsList >		DsptArgs;
		typedef DispatchMouseEvent< ID >		DispatcherType;
		typedef DsptArgsList							HandlerArgsList;
		typedef Loki::Tuple< HandlerArgsList >			HandlerArgs;
		typedef Loki::Functor< void, HandlerArgsList >	HandlerFtor;
	};
	
	template<>
	class EventTraits< EVLMSUP >
	{
	public:
		static const e_eventid ID = EVLMSUP;
		typedef MouseEventArgs					DsptArgsList;
		typedef Loki::Tuple< DsptArgsList >		DsptArgs;
		typedef DispatchMouseEvent< ID >		DispatcherType;
		typedef DsptArgsList							HandlerArgsList;
		typedef Loki::Tuple< HandlerArgsList >			HandlerArgs;
		typedef Loki::Functor< void, HandlerArgsList >	HandlerFtor;
	};

	template<>
	class EventTraits< EVRMSDOWN >
	{
	public:
		static const e_eventid ID = EVRMSDOWN;
		typedef MouseEventArgs					DsptArgsList;
		typedef Loki::Tuple< DsptArgsList >		DsptArgs;
		typedef DispatchMouseEvent< ID >		DispatcherType;
		typedef DsptArgsList							HandlerArgsList;
		typedef Loki::Tuple< HandlerArgsList >			HandlerArgs;
		typedef Loki::Functor< void, HandlerArgsList >	HandlerFtor;
	};

	template<>
	class EventTraits< EVRMSUP >
	{
	public:
		static const e_eventid ID = EVRMSUP;
		typedef MouseEventArgs					DsptArgsList;
		typedef Loki::Tuple< DsptArgsList >		DsptArgs;
		typedef DispatchMouseEvent< ID >		DispatcherType;
		typedef DsptArgsList							HandlerArgsList;
		typedef Loki::Tuple< HandlerArgsList >			HandlerArgs;
		typedef Loki::Functor< void, HandlerArgsList >	HandlerFtor;
	};

	template<>
	class EventTraits< EVMSMOVE >
	{
	public:
		static const e_eventid ID = EVMSMOVE;
		typedef MouseEventArgs					DsptArgsList;
		typedef Loki::Tuple< DsptArgsList >		DsptArgs;
		typedef DispatchMouseEvent< ID >		DispatcherType;
		typedef DsptArgsList							HandlerArgsList;
		typedef Loki::Tuple< HandlerArgsList >			HandlerArgs;
		typedef Loki::Functor< void, HandlerArgsList >	HandlerFtor;
	};

	template<>
	class EventTraits< EVMSENTER >
	{
	public:
		static const e_eventid ID = EVMSENTER;
		typedef NoArgs							DsptArgsList;
		typedef Loki::Tuple< DsptArgsList >		DsptArgs;
		typedef DispatchMouseEvent< ID >		DispatcherType;
		typedef DsptArgsList							HandlerArgsList;
		typedef Loki::Tuple< HandlerArgsList >			HandlerArgs;
		typedef Loki::Functor< void, HandlerArgsList >	HandlerFtor;
	};

	template<>
	class EventTraits< EVMSLEAVE >
	{
	public:
		static const e_eventid ID = EVMSLEAVE;
		typedef NoArgs							DsptArgsList;
		typedef Loki::Tuple< DsptArgsList >		DsptArgs;
		typedef DispatchMouseEvent< ID >		DispatcherType;
		typedef DsptArgsList							HandlerArgsList;
		typedef Loki::Tuple< HandlerArgsList >			HandlerArgs;
		typedef Loki::Functor< void, HandlerArgsList >	HandlerFtor;
	};

	template<>
	class EventTraits< EVKEYDOWN >
	{
	public:
		static const e_eventid ID = EVKEYDOWN;
		typedef KeyEventArgs					DsptArgsList;
		typedef Loki::Tuple< DsptArgsList >		DsptArgs;
		typedef DispatchFocused< ID >			DispatcherType;
		typedef DsptArgsList							HandlerArgsList;
		typedef Loki::Tuple< HandlerArgsList >			HandlerArgs;
		typedef Loki::Functor< void, HandlerArgsList >	HandlerFtor;
	};

	template<>
	class EventTraits< EVKEYUP >
	{
	public:
		static const e_eventid ID = EVKEYUP;
		typedef KeyEventArgs					DsptArgsList;
		typedef Loki::Tuple< DsptArgsList >		DsptArgs;
		typedef DispatchFocused< ID >			DispatcherType;
		typedef DsptArgsList							HandlerArgsList;
		typedef Loki::Tuple< HandlerArgsList >			HandlerArgs;
		typedef Loki::Functor< void, HandlerArgsList >	HandlerFtor;
	};

	template<>
	class EventTraits< EVCHAR >
	{
	public:
		static const e_eventid ID = EVCHAR;
		typedef KeyEventArgs					DsptArgsList;
		typedef Loki::Tuple< DsptArgsList >		DsptArgs;
		typedef DispatchFocused< ID >			DispatcherType;
		typedef DsptArgsList							HandlerArgsList;
		typedef Loki::Tuple< HandlerArgsList >			HandlerArgs;
		typedef Loki::Functor< void, HandlerArgsList >	HandlerFtor;
	};

	template<>
	class EventTraits< EVMOVE >
	{
	public:
		static const e_eventid ID = EVMOVE;
		typedef PosArgs							DsptArgsList;
		typedef Loki::Tuple< DsptArgsList >		DsptArgs;
		typedef DispatchSelfOnly< ID >			DispatcherType;
		typedef DsptArgsList							HandlerArgsList;
		typedef Loki::Tuple< HandlerArgsList >			HandlerArgs;
		typedef Loki::Functor< void, HandlerArgsList >	HandlerFtor;
	};

	template<>
	class EventTraits< EVRESIZE >
	{
	public:
		static const e_eventid ID = EVRESIZE;
		typedef SizeArgs						DsptArgsList;
		typedef Loki::Tuple< DsptArgsList >		DsptArgs;
		typedef DispatchSelfOnly< ID >			DispatcherType;
		typedef DsptArgsList							HandlerArgsList;
		typedef Loki::Tuple< HandlerArgsList >			HandlerArgs;
		typedef Loki::Functor< void, HandlerArgsList >	HandlerFtor;
	};
}

#endif
